﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AgileFx.ORM.Materialization;
using System.Linq.Expressions;
using AgileFx.ORM;
using AgileFx.ORM.Backends.LinqToSql;
using AgileFx.ORM.Utils;
using AgileFx.ORM.QueryAnalysis;

namespace AgileFx.MVC.PerformanceTools
{
    public class TracingResultListMaterializer<T> : ResultListMaterializer<T>
    {
        public TracingResultListMaterializer(EntityContext context)
            : base(context)
        { }

        public override IEnumerable<T> GetResultList(Expression expression)
        {
            var visitor = new QueryTranslationVisitor(new QueryAnalysisContext(entityContext._InternalServices.TypeTranslationUtil) { ModifyProjection = true });
            var translationResults = visitor.GetTranslatedResults(expression);

            var tableEntityQuery = translationResults.AnalysisContext.RootEntityQuery.TableEntityQuery
                .Provider.CreateQuery(translationResults.TranslatedExpression);

            Guid guid = Guid.NewGuid();
            PerformanceSpy.TraceContext.WriteToLog("BEGIN RESULT LIST MATERIALIZATION", guid.ToString());
            var result = base.GetResultList(expression);
            PerformanceSpy.TraceContext.WriteToLog("END RESULT LIST MATERIALIZATION", guid.ToString());

            var l2sDataContext = (entityContext._InternalServices.TableEntityContext as DataContextWrapper).LinqToSqlContext;
            var commandText = l2sDataContext.GetCommand(tableEntityQuery).CommandText;
            PerformanceSpy.TraceContext.WriteToLog("SQL", commandText);

            if (TypesUtil.IsPrimitiveDataType(typeof(T)))
                return tableEntityQuery as IEnumerable<T>;
            else
            {
                var tableEntities = new List<object>();
                foreach (object o in tableEntityQuery)
                    tableEntities.Add(o);

                return MakeResultList(tableEntities, translationResults.AnalysisContext.QueryableType.EnumerableItemType);
            }
        }
    }
}
